(function(){
    var StringUtils     = require('StringUtils'),
    	Collections     = require('Collections'),
    	ObjectUtils     = require('ObjectUtils');
    
    var Map        = Collections.Map,
        iterate    = Collections.iterate,
        formatEach = StringUtils.formatEach,
        combine    = Collections.combine,
        gcs        = Collections.gcs;
	
    var format = StringUtils.format;
	
	namespace('org.jsmud');
	
	org.jsmud.Command = function(commandService, name){
		this.commandService = commandService;
		this.session        = commandService.session;
		this.name           = name;
	};
	org.jsmud.Command.prototype = {
		_do : function(fnct, args, onResponse){
			var response;
			this.onResponse = onResponse;
			try{
				response = fnct.apply(this, args);
			}catch(e){
				console.log(e)
				response = {err:'Failed : ' + name + '(' + args + ') - ' + e};
			}
			if( onResponse && response ){
				onResponse(response);
			}
		},
		autoComplete : function(value, onResponse){
			if( !this.onAutoComplete ) return;
			
			this._do( this.onAutoComplete, [value], onResponse );
		},
		execute : function(args, onResponse){
			if( !this.onExecute ) return;
			
			this._do( this.onExecute, args, onResponse );
		}
	};
	
	var tmp = [];
	tmp["'"] = function(){
		var echo = '';
		iterate(arguments, function(arg){
			if( echo ) echo += ' '
			echo += arg;
		})
		this.onResponse(echo);
	};
	tmp['random'] = function(max){
		if(!max) max = 6;
		this.onResponse(Math.floor(Math.random() * max));
	};
	tmp['listRooms'] = function(){
		var scope = this;
		var roomService = scope.getService('org.jsmud.RoomService');
		roomService.list(function(list){
			var results = {values:list.results};
			results.toHTML = function(){
				return combine(formatEach(results.values, '[<span>${_id.$oid}</span>] ${name} &nbsp;'));
			};
			scope.onResponse(results);
		})
	};

	tmp['jumpTo'] = {
		onAutoComplete : function(id){
			var scope = this;
			var roomService = this.getService('org.jsmud.RoomService');
			roomService.list(function(list){
				var toString = function(i){
					return i._id.$oid;
				}
				var values = filter(list.results, '^' + id, toString);
				var results = {values:values, base:_gcs(values,toString)}
				results.toHTML = function(){
					return combine(formatEach(values, '[<span>${_id.$oid}</span>] ${name} &nbsp;'));
				}
				if( scope.onResponse ){
					scope.onResponse(results);
				}
			});
		},
		onExecute : function(id){
			var scope = this;
			var roomService = this.getService('org.jsmud.RoomService');
			roomService.load(id, function(obj){
				scope.svc.doExecute('describe', null, scope.onResponse);
			});
		}
	};
	tmp['with'] = {
		onAutoComplete : function(name){
			var parent = this;
			var serviceNames = [];
			iterate(this.svc.services, function(item, svcname){ serviceNames.push(svcname) })
			
			var values = filter(serviceNames, '^'+name);
			var result = {base:gcs(values), values:values};
			this.onResponse(result)
		},
		onExecute : function(serviceName){
			var parent = this.svc;
			var service = this.getService(serviceName);
			if( service ){
				parent.currentContext = service;
			}
		}
	};
	tmp['set'] = {
		onAutoComplete : function(value){
			var ctx = this.svc.getCurrentContext();
			if( !ctx.current() ){
				this.onResponse({err:"Failed - No Current Context"});
				return;
			}
			var values = [];
			iterate(ctx.current(), function(value, property){ values.push(property); });
			
			if( value )
				values = filter(values, '^' + value);
			var result = {base:gcs(values), values:values};
			result.toHTML = function(){
				return spanWrap(values);
			}
			this.onResponse(result);
		},
		onExecute : function(property){
			var value = '';
			if( arguments.length == 2 )
				value = arguments[1];
			else if( arguments.length > 2 ){
				for(var i=1; i < arguments.length; i++)
					value += arguments[i];
			}
			var ctx = this.svc.getCurrentContext();
			if( value[0] == '/' )
				value = eval('(' + value.substring(1) + ')');
			else
				value = trimQuote(value);
			ctx.current()[property] = value;
			
		}
	};
	tmp['this'] = {
		onExecute : function(){
			var ctx = this.svc.getCurrentContext();
			this.onResponse(format('${0}', ctx));
		}
	};
	/*
	tmp['describe'] = function(){
		var roomService = this.getService('org.jsmud.RoomService');
		var room = roomService.room;
		if( room ){
			var exits = [];
			if( !room.exits ) exits = 'None';
			else exits = combine(formatEach(room.exits, '<span>${name}</span> '));
				
			this.onResponse('['+room.name+']');
			this.onResponse(room.description);
			this.onResponse('&nbsp;');
			this.onResponse('Obvious Exits: ' + exits)
		}
	};
	*/
	tmp['save'] = function(description){
		var context = this.svc.getCurrentContext();
		context.save();
	};
	tmp['create'] = function(name, description){
		var roomService = this.getService('org.jsmud.RoomService');
		var scope = this;
		var newRoom = {
			name : trimQuote(name)
			,description : trimQuote(description)
		};
		this.getDb().save(newRoom, function(response){
			roomService.load(response.oids[0].$oid, function(obj){
				scope.svc.doExecute('describe', null, scope.onResponse);
			});
		}, function(err){
			console.log(err);
		});
	};
	

})();